﻿using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;

public class ABCheckUpdate : Singleton<ABCheckUpdate>
{
    private int downedNum;
    public uint totalBytes;
    public uint curBytes;

    public string clientVer;
    public string serverVer;
    public bool updated;

    private FileData clientList;
    private FileData serverList;
    private List<ResData> updateList;
    private List<ResData> removeList;

    private StringBuilder sb = new StringBuilder();

    public float LoadProgress
    {
        get
        {
            float num = 0;
            if (totalBytes != 0)
            {
                num = (float)curBytes / totalBytes;
            }
            return num;
        }
    }

    public void Start()
    {
        ZEventCenter.AddEventListener(ConstData.AGREE_UPDATE, LoadUpdate);
        LoadClientVer();
    }

    /// <summary>
    /// 加载客户端版本号
    /// </summary>
    private void LoadClientVer()
    {
        string clientPath = PathUtil.CheckPath(PathUtil.VER_PATH);
        ByteLoadMgr.GetSingleton().GetAssetBundle(clientPath, (string url, byte[] abBytes) =>
        {
            //clientList = ReadVS(abBytes);
            clientVer = Encoding.UTF8.GetString(abBytes);
#if !UPDATE
            ZEventCenter.DispatchEvent(new ZEvent(ConstData.FLOW_CHECK_UPDATE));
#else
            LoadServerVer();
#endif
        });
    }

    /// <summary>
    /// 加载资源服务器版本号
    /// </summary>
    private void LoadServerVer()
    {
        sb.Length = 0;
        sb.Append(GlobalString.SERVER_URL).Append(PathUtil.VER_PATH);
        ByteLoadMgr.GetSingleton().GetAssetBundle(sb.ToString(), (string url, byte[] abBytes) =>
        {
            //serverList = ReadVS(abBytes);
            serverVer = Encoding.UTF8.GetString(abBytes);
            CheckVer();
        });
    }

    private void CheckVer()
    {
        if (clientVer == serverVer)
        {
            ZEventCenter.DispatchEvent(new ZEvent(ConstData.FLOW_CHECK_UPDATE));
            return;
        }
        LoadClientVS();
    }

    /// <summary>
    /// 加载客户端资源版本配置
    /// </summary>
    private void LoadClientVS()
    {
        string clientPath = PathUtil.CheckPath(PathUtil.VS_CONFIG);
        ByteLoadMgr.GetSingleton().GetAssetBundle(clientPath, (string url, byte[] abBytes) =>
        {
            clientList = ReadVS(abBytes);
            LoadServerVS();
        });
    }

    /// <summary>
    /// 加载资源服务器资源版本配置
    /// </summary>
    private void LoadServerVS()
    {
        sb.Length = 0;
        sb.Append(GlobalString.SERVER_URL).Append(PathUtil.VS_CONFIG);
        ByteLoadMgr.GetSingleton().GetAssetBundle(sb.ToString(), (string url, byte[] abBytes) =>
        {
            serverList = ReadVS(abBytes);
            Check();
        });
    }

    private void Check()
    {
        updateList = new List<ResData>();
        removeList = new List<ResData>();

        for (int idx = 0; idx < serverList.files.Count; ++idx)
        {
            int clientIdx = clientList.files.IndexOf(serverList.files[idx]);
            ResData client = clientList.resData[clientIdx];
            ResData server = clientList.resData[clientIdx];
            if (clientIdx < 0 || !client.mDataMD5.Equals(server.mDataMD5))
            {
                updateList.Add(serverList.resData[idx]);
            }
        }

        for (int idx = 0; idx < clientList.files.Count; ++idx)
        {
            if (!serverList.files.Contains(clientList.files[idx]))
            {
                removeList.Add(clientList.resData[idx]);
            }
        }

        DelOverFile();
        if (updateList.Count > 0)
        {
            EDebug.Log(string.Format("需要更新{0}个资源", updateList.Count));
            LoadBoardMgr.GetSingleton().SetDescri(GlobalString.update);
            LoadUpdate(); CalUpdateSize();
            LoadBoardMgr.GetSingleton().ShowUpdate();
            LoadBoardMgr.GetSingleton().AskUpdate();
        }
        else
        {
            EDebug.Log("无资源更新，进入游戏");
            LoadBoardMgr.GetSingleton().HideUpdate();
            LoadedAll();//为了显示出进度
        }
    }

    /// <summary>
    /// 删除本地多余文件
    /// </summary>
    private void DelOverFile()
    {
        if (removeList.Count > 0)
        {
            for (int i = 0; i < removeList.Count; i++)
            {
                clientList.RemoveResData(removeList[i]); sb.Length = 0;
                sb.Append(Application.persistentDataPath).Append("/").Append(removeList[i].mDataPath);
                string fileName = sb.ToString();
                if (File.Exists(fileName))
                {
                    EDebug.Log(string.Format("版本更新,删除文件:{0}", fileName));
                    File.Delete(fileName);
                }
            }
            removeList.Clear();
            WriteClientVS(clientList);
        }
    }

    private void CalUpdateSize()
    {
        for (int i = 0; i < updateList.Count; i++)
        {
            totalBytes += updateList[i].mSize;
        }
    }

    private void LoadUpdate(ZEvent ev = null)
    {
        ZEventCenter.AddEventListener(ConstData.ABMGR_LOAD_COMPLETE, LoadedAll);
        for (int i = 0; i < updateList.Count; i++)
        {
            sb.Length = 0; string str = updateList[i].mDataPath;
            sb.Append(GlobalString.SERVER_URL).Append(str);
            ByteLoadMgr.GetSingleton().GetAssetBundle(sb.ToString(), LoadedHandler, str);
        }
        //处理更新进度界面
        LoadBoardMgr.GetSingleton().DisUpdate();
    }

    private void LoadedAll(ZEvent ev = null)
    {
        EDebug.Log("资源更新工作完成");
        //关闭更新界面
        LoadBoardMgr.GetSingleton().HideUpdate();

        //更新完成标志
        updated = true;
        //写入客户端版本号
        clientVer = serverVer;
        WriteClientVer();

        ZEventCenter.DispatchEvent(new ZEvent(ConstData.FLOW_CHECK_UPDATE));
        ZEventCenter.RemoveEventListener(ConstData.AGREE_UPDATE, LoadUpdate);
    }

    private void LoadedHandler(string key, byte[] abBytes)
    {
        WriteByteFile(key, abBytes);
        curBytes += (uint)abBytes.Length;
        ResData rd = serverList.resData[serverList.files.IndexOf(key)];
        clientList.AddResData(rd); downedNum++;
        if (downedNum >= GlobalNum.SAVE_NUM)
        {
            downedNum = 0;
            WriteClientVS(clientList);
        }
    }

    /// <summary>
    /// 写入客户端资源版本配置
    /// </summary>
    /// <param name="fileList"></param>
    private void WriteClientVS(FileData fileList)
    {
        WriteTextFile(PathUtil.VS_CONFIG, fileList.ToString());
    }

    /// <summary>
    /// 写入客户端资源版本号
    /// </summary>
    private void WriteClientVer()
    {
        WriteTextFile(PathUtil.VER_PATH, clientVer.ToString());
    }

    /// <summary>
    /// 写入文本到文件
    /// </summary>
    /// <param name="key"></param>
    /// <param name="text"></param>
    private void WriteTextFile(string key, string text)
    {
        WriteByteFile(key, Encoding.UTF8.GetBytes(text));
    }

    /// <summary>
    /// 写入字节到文件
    /// </summary>
    /// <param name="key"></param>
    /// <param name="abBytes"></param>
    private void WriteByteFile(string key, byte[] abBytes)
    {
        sb.Length = 0;
        sb.Append(Application.persistentDataPath).Append("/").Append(key);
        string fileName = sb.ToString();
        FileInfo info = new FileInfo(fileName);
        info.Directory.Create();
        File.WriteAllBytes(fileName, abBytes);
    }

    /// <summary>
    /// 解析资源版本配置
    /// </summary>
    /// <param name="ab"></param>
    /// <param name="vsDic"></param>
    private FileData ReadVS(byte[] bytes)
    {
        FileData fileList = new FileData();
        MemoryStream stream = new MemoryStream(bytes);
        StreamReader reader = new StreamReader(stream);
        fileList = JsonConvert.DeserializeObject<FileData>(reader.ReadToEnd());
        fileList.ReadBytes(bytes); stream.Dispose();
        reader.Close(); reader.Dispose();
        return fileList;
    }
}